package com.jprocms.module.cms.service.content;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jpro.framework.common.pojo.PageResult;
import com.jpro.framework.common.util.collection.CollectionUtils;
import com.jpro.framework.security.core.util.SecurityFrameworkUtils;
import com.jprocms.module.cms.controller.admin.content.tagvo.TagCreateReqVO;
import com.jprocms.module.cms.controller.admin.content.tagvo.TagExportReqVO;
import com.jprocms.module.cms.controller.admin.content.tagvo.TagPageReqVO;
import com.jprocms.module.cms.controller.admin.content.tagvo.TagUpdateReqVO;
import com.jprocms.module.cms.convert.content.TagConvert;
import com.jprocms.module.cms.dal.dataobject.content.ContentTagDo;
import com.jprocms.module.cms.dal.dataobject.content.TagDO;
import com.jprocms.module.cms.dal.mysql.content.ContentTagMapper;
import com.jprocms.module.cms.dal.mysql.content.TagMapper;
import com.jprocms.module.cms.util.CmsContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.constant.CmsSysConstants.COLL_SPT;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.COMMON_PARAM_ERROR;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.TAG_NOT_EXISTS;

/**
 * tag词 Service 实现类
 *
 * @author jprocms
 */
@Service
@Validated
public class TagServiceImpl implements TagService {

    @Resource
    private TagMapper tagMapper;

    @Resource
    private ContentTagMapper contentTagMapper;

    @Override
    public Long createTag(TagCreateReqVO createReqVO) {
        if(StringUtils.isBlank(createReqVO.getTagName())){
            return 0L;
        }
        // 插入
        TagDO tag = TagConvert.INSTANCE.convert(createReqVO);
        tag.setSiteId(CmsContextUtil.getCurrSiteId());
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        tag.setUserId(userId);
        tagMapper.insert(tag);
        // 返回
        return tag.getId();
    }

    @Override
    public void updateTag(TagUpdateReqVO updateReqVO) {
        // 校验存在
        validateTagExists(updateReqVO.getId());
        if(StringUtils.isBlank(updateReqVO.getTagName())){
            return;
        }
        // 更新
        TagDO updateObj = TagConvert.INSTANCE.convert(updateReqVO);
        tagMapper.updateById(updateObj);
    }

    @Override
    public void deleteTag(Long id) {
        // 校验存在
        validateTagExists(id);
        // 删除
        tagMapper.deleteById(id);
    }


    /**
     * tag词
     *
     * @param tags
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Set<Long> saveTags(Long contentId, String tags) {
        Assert.notNull(contentId, () -> {
            throw exception(COMMON_PARAM_ERROR);
        });
        LambdaQueryWrapper<ContentTagDo> queryWrapper = Wrappers.lambdaQuery(ContentTagDo.class);
        queryWrapper.eq(ContentTagDo::getContentId, contentId);
        contentTagMapper.delete(queryWrapper);
        List<String> tagNameList = StrUtil.split(tags, COLL_SPT);
        if (CollUtil.isNotEmpty(tagNameList)) {
            List<TagDO> tagDOS = tagMapper.selectList(TagDO::getTagName, tagNameList);
            Set<Long> tagIds = CollectionUtils.convertSet(tagDOS, TagDO::getId);
            Set<String> existTagNames = CollectionUtils.convertSet(tagDOS, TagDO::getTagName);
            List<String> toSaveTagNames = CollUtil.subtractToList(tagNameList, existTagNames).stream().filter(t->StringUtils.isNotBlank(t)).collect(Collectors.toList());
            for (String tagName : toSaveTagNames) {
                Long tagId = createTag(new TagCreateReqVO(tagName));
                tagIds.add(tagId);
            }
            List<ContentTagDo> contentTagDos = new ArrayList<>();
            tagIds.forEach(tagId -> {
                ContentTagDo tagDo = new ContentTagDo(contentId, tagId);
                contentTagDos.add(tagDo);
            });
            contentTagMapper.insertBatch(contentTagDos);
            return tagIds;
        }
        return null;
    }

    private void validateTagExists(Long id) {
        if (tagMapper.selectById(id) == null) {
            throw exception(TAG_NOT_EXISTS);
        }
    }

    @Override
    public TagDO getTag(Long id) {
        return tagMapper.selectById(id);
    }

    @Override
    public List<TagDO> getTagList(Collection<Long> ids) {
        return tagMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<TagDO> getTagPage(TagPageReqVO pageReqVO) {
        final PageResult<TagDO> tagDOPageResult = tagMapper.selectPage(pageReqVO);
        tagDOPageResult.adjustPages(pageReqVO);
        return tagDOPageResult;
    }

    @Override
    public List<TagDO> getTagList(TagExportReqVO reqVO) {
        return tagMapper.selectList(reqVO);
    }
}
